import { Box, Button, Paper, TextField, Tooltip } from "@mui/material";
import { useSnackbar } from "notistack/dist";
import React, { useEffect, useRef, useState } from "react";
import MyButton from "../../components/MyButton";
import RandomButton from "../../components/RandomButton";
import Circle from "./Circle";

export default function Heap(props) {
  const [line, setLine] = useState([]);
  const [node, setNode] = useState([]);
  const [isSorting, setIsSorting] = useState(false);
  const [ipt, setIpt] = useState();
  const [midNode, setMidNode] = useState([]);
  const [mx, setMx] = useState(0);
  const mount = useRef(false);
  const { msg, setMsg } = props;
  var tline = [],
    tnode = [],
    len,
    tmsg = msg;
  const { enqueueSnackbar } = useSnackbar();
  const upd = () => {
    var tmp = [];
    // console.log(tnode);
    for (var i in tnode) {
      tmp[tnode[i].pos] = tnode[i];
    }
    // console.log(tmp);
    setNode([...tmp]);
    setLine([...tline]);
  };
  useEffect(() => {
    setMsg({
      sentence: "堆排序",
      sT: 0,
      cT: 0,
      tot: 0,
    });
    mount.current = true;
    return () => (mount.current = false);
  }, []);

  const sleep = (time) => {
    return new Promise(function (resolve) {
      setTimeout(resolve, time * props.speed);
    });
  };

  const build = async () => {
    if (isSorting) {
      enqueueSnackbar("正在进行操作", { variant: "error" });
      return;
    }

    if (ipt == null) {
      enqueueSnackbar("请输入以英文逗号分隔的整数", { variant: "error" });
      return;
    }
    setIsSorting(true);
    var tmp = ipt.split(",").map((val) => +val);

    for (var i in tmp) {
      if (isNaN(tmp[i])) {
        enqueueSnackbar("请输入以英文逗号分隔的整数", { variant: "error" });
        return;
      }
    }

    len = tmp.length;
    tmsg = { sT: 0, cT: 0, tot: len, sentence: "堆排序" };
    if (mount.current) setMsg({ ...tmsg });
    else return;
    setMx(len);
    tnode[0] = {
      number: tmp[0],
      pos: 0,
      posx: 33,
      wd: 65,
      posy: 0,
      color: "black",
    };

    tline = [];
    for (var i = 0; i < len; ++i) {
      tnode[i] = {
        ...tnode[i],
        number: tmp[i],
        pos: i,
        color: "black",
      };

      if (i * 2 + 1 < len) {
        tnode[i * 2 + 1] = {
          posx: tnode[i].posx - tnode[i].wd / 4,
          wd: tnode[i].wd / 2,
          posy: tnode[i].posy + 1,
        };
        tline.push({
          x1: `${tnode[i].posx}vw`,
          y1: `${tnode[i].posy * 70 + 70}px`,
          x2: `${tnode[i * 2 + 1].posx}vw`,
          y2: `${tnode[i * 2 + 1].posy * 70 + 70}px`,
        });
      }

      if (i * 2 + 2 < len) {
        tnode[i * 2 + 2] = {
          posx: tnode[i].posx + tnode[i].wd / 4,
          wd: tnode[i].wd / 2,
          posy: tnode[i].posy + 1,
        };

        tline.push({
          x1: `${tnode[i].posx}vw`,
          y1: `${tnode[i].posy * 70 + 70}px`,
          x2: `${tnode[i * 2 + 2].posx}vw`,
          y2: `${tnode[i * 2 + 2].posy * 70 + 70}px`,
        });
      }
    }

    upd();
    await sleep(500);

    for (var i = len - 1; i >= 0; --i) {
      if (i * 2 + 1 < len || i * 2 + 2 < len) {
        // console.log(i);
        tnode[i].color = "red";
        upd();
        await sleep(400);

        await down(i);
      }
    }

    setMidNode([...tnode]);
    setIsSorting(false);
  };
  const swap = (x, p) => {
    var tmp = tnode[p];

    /**
     * posx、posy与在tnode中的位置绑定
     * 其他随一起交换
     */
    tnode[p] = {
      ...tnode[x],
      posx: tnode[p].posx,
      posy: tnode[p].posy,
      wd: tnode[p].wd,
      // posx: tnode[x].posx,
      // posy: tnode[x].posy,
    };

    tnode[x] = {
      ...tmp,
      wd: tnode[x].wd,
      posx: tnode[x].posx,
      posy: tnode[x].posy,
    };
  };

  const down = async (x) => {
    // console.log(tnode[x].pos);

    var p = x + x + 1;
    if (p >= len) {
      tnode[x].color = "black";

      // console.log(tnode[x].pos, tnode[x].color);

      upd();
      await sleep(400);

      return;
    }

    if (p + 1 < len && tnode[p].number > tnode[p + 1].number) ++p;

    tmsg = {
      ...tmsg,
      cT: tmsg.cT + 1,
      sentence: "比较" + tnode[x].number + "和" + tnode[p].number,
    };
    if (mount.current) setMsg({ ...tmsg });
    else return;

    if (tnode[p].number >= tnode[x].number) {
      tnode[x].color = "black";
      upd();
      await sleep(400);
      return;
    }
    tmsg = {
      ...tmsg,
      sT: tmsg.sT + 1,
      sentence: "交换" + tnode[x].number + "和" + tnode[p].number,
    };
    if (mount.current) setMsg({ ...tmsg });
    else return;
    swap(x, p);
    upd();
    await sleep(500);

    await down(p);
  };
  const up = async (p) => {
    if (p == 0) {
      tnode[p].color = "black";
      upd();
      await sleep(400);
      return;
    }

    var fa = Math.floor((p - 1) / 2);

    tmsg = {
      ...tmsg,
      cT: tmsg.cT + 1,
      sentence: "比较" + tnode[p].number + "和" + tnode[fa].number,
    };
    if (mount.current) setMsg({ ...tmsg });
    else return;

    if (tnode[fa].number <= tnode[p].number) {
      tnode[p].color = "black";
      upd();
      await sleep(400);
      return;
    }

    tmsg = {
      ...tmsg,
      sT: tmsg.sT + 1,
      sentence: "交换" + tnode[p].number + "和" + tnode[fa].number,
    };
    if (mount.current) setMsg({ ...tmsg });
    else return;

    swap(fa, p);
    upd();
    await sleep(400);
    await up(fa);
  };

  const del = async () => {
    if (isSorting) {
      enqueueSnackbar("正在进行操作", { variant: "error" });
      return;
    }

    tnode = [...midNode];
    tline = [...line];
    len = tnode.length;

    if (len == 0) {
      enqueueSnackbar("空树无法删点", { variant: "error" });
      return;
    }

    setIsSorting(true);

    tnode[len - 1].color = "red";

    swap(0, len - 1);

    // console.log(tline);
    tline = tline.splice(0, len - 2);
    // console.log(tline);
    tnode = tnode.splice(0, len - 1);
    tmsg = {
      sentence: tnode[0].number + "替换根节点",
      sT: 0,
      cT: 0,
      tot: len - 1,
    };
    if (mount.current) setMsg({ ...tmsg });
    else return;

    --len;
    upd();
    await sleep(500);

    if (len > 0) {
      await down(0);
      upd();
      await sleep(400);
      tnode[0].color = "black";
    }

    setMidNode([...tnode]);
    // console.log(midNode, tnode);
    setIsSorting(false);
  };
  const addNode = async () => {
    if (ipt == null) {
      enqueueSnackbar("请输入单个整数", { variant: "error" });
      return;
    }

    var tmp = +ipt;

    if (isSorting) {
      enqueueSnackbar("正在进行操作", { variant: "error" });
      return;
    }
    if (isNaN(tmp)) {
      enqueueSnackbar("请输入单个整数", { variant: "error" });
      return;
    }
    tnode = [...midNode];
    tline = [...line];
    len = tnode.length;

    if (tnode.length == 0) {
      enqueueSnackbar("请先建立一棵非空树", { variant: "error" });
      return;
    }
    // console.log(tnode);

    setIsSorting(true);

    var p = Math.floor((len - 1) / 2);

    tnode.push({
      pos: mx,
      number: tmp,
      posx:
        len % 2 == 1
          ? tnode[p].posx - tnode[p].wd / 4
          : tnode[p].posx + tnode[p].wd / 4,
      wd: tnode[p].wd / 2,
      color: "red",
      posy: tnode[p].posy + 1,
    });

    tline.push({
      x1: `${tnode[p].posx}vw`,
      y1: `${tnode[p].posy * 70 + 70}px`,
      x2: `${tnode[len].posx}vw`,
      y2: `${tnode[len].posy * 70 + 70}px`,
    });

    ++len;

    tmsg = { sentence: "添加" + tmp + "到最后", sT: 0, cT: 0, tot: len };
    if (mount.current) setMsg({ ...tmsg });
    else return;
    upd();
    await sleep(400);
    // console.log(tnode);

    await up(len - 1);

    setMx(mx + 1);

    setMidNode([...tnode]);
    setIsSorting(false);
  };

  return (
    <div style={{ display: "flex", marginTop: 3, flexDirection: "column" }}>
      <Paper elevation={3}>
        <svg width="65vw" height="520px">
          {/* <Circle posx={100} color="red" number={3} posy={0} /> */}
          {line.map(
            (val) =>
              val != null && (
                <line
                  x1={val.x1}
                  x2={val.x2}
                  y1={val.y1}
                  y2={val.y2}
                  strokeWidth="2"
                  stroke="black"
                />
              )
          )}
          {node.map(
            (val) =>
              val != null && (
                <Circle
                  posx={val.posx}
                  posy={val.posy}
                  number={val.number}
                  color={val.color}
                />
              )
          )}
        </svg>
        <Box
          sx={{
            width: "100%",
            display: "flex",
            flexDirection: "column",
            alignItems: "center",
            // marginTop: 20,
          }}
        >
          <TextField
            size="small"
            value={ipt}
            onChange={(e) => setIpt(e.target.value)}
          />
          {/* <Box sx={{ marginTop: 3, display: "felx", flexDirection: "column" }}> */}
          <Box sx={{ display: "flex", flexDirection: "row" }}>
            <Tooltip placement="left" title="输入以英文逗号分隔的整数">
              <MyButton
                loading={isSorting}
                variant="contained"
                onClick={build}
                sx={{ marginTop: 2 }}
              >
                {isSorting ? "正在排序" : "构建树"}
              </MyButton>
            </Tooltip>
            <Tooltip placement="left" title="输入单个整数">
              <MyButton
                loading={isSorting}
                variant="contained"
                onClick={addNode}
                sx={{ marginTop: 1 }}
              >
                {isSorting ? "正在排序" : "添加节点"}
              </MyButton>
            </Tooltip>
            <MyButton
              loading={isSorting}
              variant="contained"
              onClick={del}
              sx={{ marginTop: 1 }}
            >
              {isSorting ? "正在排序" : "删除堆顶"}
            </MyButton>
            {/* </Box> */}
            <RandomButton setData={setIpt} loading={isSorting}></RandomButton>
          </Box>
        </Box>
      </Paper>
    </div>
  );
}
